<?php

class Account extends Validation {
	private $guid = null;
	private $name = null;
	private $username = null;
	private $password = null;
	private $email = null;
	private $secret_question = null;
	private $secret_answer = null;
	private $personal_id = 11111110000000;
	private $block = false;
	
	private $md5 = false;
	
	private $characters = array();
	private $data = array();
	private $validates = array();
	
	public function __construct($username = null) {
		if (!is_null($username)) {
			$this->username($username);
			$this->find($username);
		}
	}
	
	public function errors() {
		return $this->errors;
	}
	
	public function is_valid() {
		return empty($this->errors);
	}
	
	public function validate($validates = array()) {
		$this->validates += $validates;
		return $this;
	}
	
	public function data() {
		return $this->data;
	}
	
	public function name($name = null) {
		if (is_null($name)) {
			return $this->name;
		}
		$this->name = $name;
		return $this;
	}	
	
	public function username($username = null) {
		if (is_null($username)) {
			return $this->username;
		}
		$this->username = $username;
		return $this;
	}
	
	public function password($password = null) {
		if (is_null($password)) {
			return $this->md5 ? bin2hex($this->password) : $this->password;
		}
		$this->md5 = false;
		$this->password = $password;
		return $this;
	}
	
	public function password_with_md5($password = null) {
		$this->md5 = true;
		$this->password = $this->encrypt_password($password);
	}	
	
	public function email($email = null) {
		if (is_null($email)) {
			return $this->email;
		}
		$this->email = $email;
		return $this;
	}
	
	public function guid() {
		if (!is_null($this->guid)) {
			$result = Mssql::fetch('SELECT MAX(memb_guid) AS guid FROM MEMB_INFO');
			$this->guid = $result->guid + 1;
			return $this->guid;
		}
	}
	
	public function secret_question($secret_question = null) {
		if (is_null($secret_question)) {
			return $this->secret_question;
		}
		$this->secret_question = $secret_question;
		return $this;
	}

	public function secret_answer($secret_answer = null) {
		if (is_null($secret_answer)) {
			return $this->secret_answer;
		}
		$this->secret_answer = $secret_answer;
		return $this;
	}

	public function personal_id($personal_id = null) {
		if (is_null($personal_id)) {
			return $this->personal_id;
		}
		$this->personal_id = 1111111 . $personal_id;
		return $this;
	}
	
	public function block($block = true) {
		$this->block = $block;
		return $this;
	}
	
	public function is_blocked() {
		return $this->block;
	}
	
	public function characters() {	
		$results = Mssql::fetch_all('SELECT Name AS name FROM Character WHERE AccountID = :username[string]', array('username' => $this->username()));
		foreach ($results as $character) {
			$this->characters[] = new Character($character->name);
		}
		return $this->characters;
	}
	
	public function is_online() {
		return $this->data()->connect_stat > 0;
	}
	
	public function last_used_character() {	
		return new Character($this->data()->last_used_character);
	}
	
	public function last_used_server() {
		return $this->data()->server_name;
	}
	
	public function last_connections() {
		$result = Mssql::fetch_all('SELECT 
			ac.GameIDC AS character,
			ms.IP AS ip,
			ms.ConnectStat AS connect_stat,
			ms.ServerName AS server_name,
			ms.ConnectTM AS connected_at,
			ms.DisConnectTM AS disconnected_at
			FROM MEMB_STAT ms
			JOIN AccountCharacter ac ON ms.memb___id = ac.Id
			WHERE memb___id = :username[string] 
			ORDER BY ConnectTM DESC
		', array('username' => $this->username()));
		return $result;
	}
	
	public function username_exists($username = null) {
		$result = Mssql::fetch('SELECT COUNT(1) AS total FROM MEMB_INFO WHERE memb___id = :username[string]', array('username' => $username));
		return $result->total > 0;
	}
	
	public function email_exists($email = null) {
		$result = Mssql::fetch('SELECT COUNT(1) AS total FROM MEMB_INFO WHERE mail_addr = :email[string]', array('email' => $email));
		return $result->total > 0;
	}	
	
	public function save($validate = true) {
		if ($validate) {
			$this->validates($this->validates);
			if (!$this->is_valid()) {
				return false;
			}
		}
		return true;
	}
	
	public function update($validate = true) {
		if ($validate) {
			$this->validates($this->validates);
			if (!$this->is_valid()) {
				return false;
			}
		}
		$params = array(
			'password' => $this->password(),
			'email' => $this->email(),
			'question' => $this->secret_question(),
			'answer' => $this->secret_answer(),
			'name' => $this->name(),
			'personal_id' => $this->personal_id(),
			'username' => $this->username(),
			'block' => $this->is_blocked() ? 1 : 0
		);
 		Mssql::query('UPDATE MEMB_INFO SET memb__pwd = :password[string], mail_addr = :email[string], fpas_ques = :question[string], fpas_answ = :answer[string], memb_name = :name[string], sno__numb = :personal_id[int], bloc_code = :block[int] WHERE memb___id = :username[string]', $params);		
		return true;
	}
	
	private function find($username) {
		$result = Mssql::fetch('SELECT
			mi.memb_guid AS guid,
			mi.memb___id AS username,
			mi.memb__pwd AS password,
			mi.memb_name AS name,
			mi.mail_addr AS email,
			mi.fpas_ques AS secret_question,
			mi.fpas_answ AS secret_answer,
			mi.sno__numb AS personal_id,
			mi.bloc_code AS block,
			ms.ServerName AS server_name,
			ms.ConnectStat AS connect_stat,
			ms.IP AS ip,
			ac.GameIDC AS last_used_character
			FROM MEMB_INFO mi
			LEFT JOIN MEMB_STAT ms ON mi.memb___id = ms.memb___id COLLATE DATABASE_DEFAULT
			LEFT JOIN AccountCharacter ac ON mi.memb___id = ac.Id
			WHERE mi.memb___id = :username[string]
		', array('username' => $username));
		$this->data = $result;
		if (!empty($result)) {
			foreach ($result as $key => $value) {
				if (in_array($key, array_keys(get_class_vars(__CLASS__)))) {
					$this->{$key} = $value;
				}
			}
		}
	}
	
	private function encrypt_password($password) {
		$result = Mssql::fetch('DECLARE @hash varbinary(16)
			EXEC master..XP_MD5_EncodeKeyVal :password[string], :username[string], @hash OUT
			SELECT @hash AS hash
		', array('username' => $this->username(), 'password' => $password));
		return $result->hash;
	}
}